{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# LSTM"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### LSTM是RNN的一种变种，在于RNN随着时间的推移，一些记忆会消失，于是在LSTM中，添加了遗忘门、输入门以及输出门来防止遗忘，其实遗忘的好坏是sigmoid函数来学习的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting data/train-images-idx3-ubyte.gz\n",
      "Extracting data/train-labels-idx1-ubyte.gz\n",
      "Extracting data/t10k-images-idx3-ubyte.gz\n",
      "Extracting data/t10k-labels-idx1-ubyte.gz\n"
     ]
    }
   ],
   "source": [
    "mnist = input_data.read_data_sets('data/', one_hot=True)\n",
    "INPUT = 28\n",
    "HIDDEN = 128\n",
    "OUTPUT = 10\n",
    "\n",
    "INPUT += HIDDEN\n",
    "\n",
    "ALPHA = 0.001\n",
    "BATCH_NUM = 64\n",
    "\n",
    "ITER_NUM = 1000\n",
    "LOG_ITER = ITER_NUM // 10\n",
    "PLOT_ITER = ITER_NUM // 200"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def softmax(arr):\n",
    "    c = np.clip(arr, -700, 700) # 防止溢出 \n",
    "    e = np.exp(c)\n",
    "    return e / np.sum(e, axis=1, keepdims=True)\n",
    "\n",
    "# 交叉熵\n",
    "def cross_entropy(out, label):\n",
    "    entropy = label * np.log(out + 1e-6)\n",
    "    return -np.sum(entropy, axis=1, keepdims=True)\n",
    "\n",
    "def sigmoid(arr):\n",
    "    c = np.clip(arr, -700, 700)\n",
    "    return 1 / (1 + np.exp(-c))\n",
    "\n",
    "def deriv_sigmoid(out):\n",
    "    return out * (1 - out)\n",
    "\n",
    "def tanh(arr):\n",
    "    c = np.clip(arr, -350, 350)\n",
    "    return 2 / (1 + np.exp(-2 * c)) - 1\n",
    "\n",
    "def deriv_tanh(out):\n",
    "    return 1 - np.square(out)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "errors = []\n",
    "\n",
    "wf = np.random.randn(INPUT, HIDDEN) / np.sqrt(INPUT / 2)\n",
    "wi = np.random.randn(INPUT, HIDDEN) / np.sqrt(INPUT / 2)\n",
    "wc = np.random.randn(INPUT, HIDDEN) / np.sqrt(INPUT / 2)\n",
    "wo = np.random.randn(INPUT, HIDDEN) / np.sqrt(INPUT / 2)\n",
    "wy = np.random.randn(HIDDEN, OUTPUT) / np.sqrt(HIDDEN / 2)\n",
    "\n",
    "bf = np.zeros(HIDDEN)\n",
    "bi = np.zeros(HIDDEN)\n",
    "bc = np.zeros(HIDDEN)\n",
    "bo = np.zeros(HIDDEN)\n",
    "by = np.zeros(OUTPUT)\n",
    "\n",
    "dwf = np.zeros_like(wf)\n",
    "dwi = np.zeros_like(wi)\n",
    "dwc = np.zeros_like(wc)\n",
    "dwo = np.zeros_like(wo)\n",
    "dwy = np.zeros_like(wy)\n",
    "\n",
    "dbf = np.zeros_like(bf)\n",
    "dbi = np.zeros_like(bi)\n",
    "dbc = np.zeros_like(bc)\n",
    "dbo = np.zeros_like(bo)\n",
    "dby = np.zeros_like(by)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![image.png](fig1.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def LSTM_Cell(input_val):\n",
    "    batch_num = input_val.shape[1]\n",
    "    \n",
    "    caches = []\n",
    "    states = []\n",
    "    # 初始状态 c 和 h_prev都是为0\n",
    "    states.append([np.zeros([batch_num, HIDDEN]), np.zeros([batch_num, HIDDEN])])\n",
    "        \n",
    "    for x in input_val:\n",
    "        c_prev, h_prev = states[-1]\n",
    "        x = np.column_stack([x, h_prev])\n",
    "        hf = sigmoid(np.dot(x, wf) + bf)\n",
    "        hi = sigmoid(np.dot(x, wi) + bi)\n",
    "        ho = sigmoid(np.dot(x, wo) + bo)\n",
    "        hc = tanh(np.dot(x, wc) + bc)\n",
    "    \n",
    "        c = hf * c_prev + hi * hc\n",
    "        h = ho * tanh(c)\n",
    "    \n",
    "        states.append([c, h])\n",
    "        caches.append([x, hf, hi, ho, hc])\n",
    "    return caches, states"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def predict(img):\n",
    "    input_val = np.reshape(img, [28, 1, 28])\n",
    "    \n",
    "    caches, states = LSTM_Cell(input_val)\n",
    "    c, h = states[-1]\n",
    "    \n",
    "    pred = softmax(np.dot(h, wy) + by)\n",
    "    label = np.argmax(pred)\n",
    "    \n",
    "    return label"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![image.png](fig2.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "iter 0\n",
      "entropy 148.230102882\n",
      "----------\n",
      "iter 100\n",
      "entropy 130.411356399\n",
      "----------\n",
      "iter 200\n",
      "entropy 26.9214080264\n",
      "----------\n",
      "iter 300\n",
      "entropy 35.5380413727\n",
      "----------\n",
      "iter 400\n",
      "entropy 19.3635887288\n",
      "----------\n",
      "iter 500\n",
      "entropy 16.4149703994\n",
      "----------\n",
      "iter 600\n",
      "entropy 5.40962387843\n",
      "----------\n",
      "iter 700\n",
      "entropy 9.29227429211\n",
      "----------\n",
      "iter 800\n",
      "entropy 7.63320640489\n",
      "----------\n",
      "iter 900\n",
      "entropy 19.3816912508\n",
      "----------\n",
      "iter 1000\n",
      "entropy 13.2405430479\n",
      "----------\n"
     ]
    }
   ],
   "source": [
    "for i in range(ITER_NUM+1):\n",
    "    X, Y = mnist.train.next_batch(BATCH_NUM)\n",
    "    Xt = np.transpose(np.reshape(X, [-1, 28, 28]), [1, 0, 2])\n",
    "        \n",
    "    caches, states = LSTM_Cell(Xt) # 每次的lstm单元迭代\n",
    "    c, h = states[-1]  # 获取前一个的状态\n",
    "        \n",
    "    out = np.dot(h, wy) + by #最后结果的输出\n",
    "    pred = softmax(out)\n",
    "    entropy = cross_entropy(pred, Y)   # 计算交叉熵\n",
    "    \n",
    "    # BPTT\n",
    "    dout = pred - Y  #计算误差\n",
    "    dwy = np.dot(h.T, dout)  #对wy的偏导\n",
    "    dby = np.sum(dout, axis=0) #对by的偏导\n",
    "    \n",
    "    dc_next = np.zeros_like(c) #存储下一个节点的dc\n",
    "    dh_next = np.zeros_like(h) #存储下一个节点的dh\n",
    "    \n",
    "    # 28为时间 通过28来反向传播\n",
    "    for t in range(Xt.shape[0]):\n",
    "        c, h = states[-t-1] #当前时间点的状态\n",
    "        c_prev, h_prev = states[-t-2] #前一个时间点的状态\n",
    "\n",
    "        x, hf, hi, ho, hc = caches[-t-1] #当前时间点的lstm_cell内的变量的值\n",
    "        \n",
    "        # 当前状态c的值\n",
    "        tc = tanh(c)\n",
    "        dh = np.dot(dout, wy.T) + dh_next\n",
    "        \n",
    "        \n",
    "        # 根据前面的图 \n",
    "        dc = dh * ho * deriv_tanh(tc)\n",
    "        dc = dc + dc_next\n",
    "        \n",
    "        dho = dh * tc \n",
    "        dho = dho * deriv_sigmoid(ho)\n",
    "        \n",
    "        dhf = dc * c_prev \n",
    "        dhf = dhf * deriv_sigmoid(hf)\n",
    "        \n",
    "        dhi = dc * hc \n",
    "        dhi = dhi * deriv_sigmoid(hi)\n",
    "        \n",
    "        dhc = dc * hi \n",
    "        dhc = dhc * deriv_tanh(hc)\n",
    "        \n",
    "        dwf += np.dot(x.T, dhf)\n",
    "        dbf += np.sum(dhf, axis=0)\n",
    "        dXf = np.dot(dhf, wf.T)\n",
    "        \n",
    "        dwi += np.dot(x.T, dhi)\n",
    "        dbi += np.sum(dhi, axis=0)\n",
    "        dXi = np.dot(dhi, wi.T)\n",
    "        \n",
    "        dwo += np.dot(x.T, dho)\n",
    "        dbo += np.sum(dho, axis=0)\n",
    "        dXo = np.dot(dho, wo.T)\n",
    "        \n",
    "        dwc += np.dot(x.T, dhc)\n",
    "        dbc += np.sum(dhc, axis=0)\n",
    "        dXc = np.dot(dhc, wc.T)\n",
    "\n",
    "        dX = dXf + dXi + dXo + dXc\n",
    "        \n",
    "        dc_next = hf * dc\n",
    "        dh_next = dX[:, -HIDDEN:]\n",
    "        \n",
    "    # 更新lstm中的权重\n",
    "    wf -= ALPHA * dwf\n",
    "    wi -= ALPHA * dwi\n",
    "    wc -= ALPHA * dwc\n",
    "    wo -= ALPHA * dwo\n",
    "    wy -= ALPHA * dwy\n",
    "    \n",
    "    bf -= ALPHA * dbf\n",
    "    bi -= ALPHA * dbi\n",
    "    bc -= ALPHA * dbc\n",
    "    bo -= ALPHA * dbo\n",
    "    by -= ALPHA * dby\n",
    "    \n",
    "    # 每次完成后初始化\n",
    "    dwf = 0\n",
    "    dwi = 0\n",
    "    dwc = 0\n",
    "    dwo = 0\n",
    "    dwy = 0\n",
    "    \n",
    "    dbf = 0\n",
    "    dbi = 0\n",
    "    dbc = 0\n",
    "    dbo = 0\n",
    "    dby = 0\n",
    "    \n",
    "    # 打印输出日记\n",
    "    if i % PLOT_ITER == 0:\n",
    "        errors.append(np.sum(entropy))\n",
    "    \n",
    "    if i % LOG_ITER == 0:\n",
    "        print('iter', i)\n",
    "        print('entropy', np.sum(entropy))\n",
    "        print('----------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x121fbdcf8>]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x11edb20b8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(errors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "prediction : 3\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x134edb5f8>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nQFCEHwjqfxu5Rxnzc+/XAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x121fb29e8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "i = np.random.randint(55000)\n",
    "img = mnist.train.images[i]\n",
    "img = np.reshape(img, [28, 28])\n",
    "\n",
    "pred = predict(img)\n",
    "print('prediction :', pred)\n",
    "\n",
    "plt.imshow(img, cmap='gray')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "res = 0\n",
    "for img,labels in zip(mnist.test.images,mnist.test.labels):\n",
    "    pred = predict(img)\n",
    "    res += (pred==labels.argmax())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.95599999999999996"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res / mnist.test.num_examples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
